package com.sunmnet.pub.db;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

import com.sunmnet.pub.connector.bean.DataSourceBean;
import com.sunmnet.pub.connector.bean.PdmColumn;
import com.sunmnet.pub.connector.bean.PdmTable;
import com.sunmnet.pub.db.DBType;
import com.sunmnet.pub.db.DBUtils;
import com.sunmnet.pub.db.exception.NoConfException;
import com.sunmnet.pub.db.splitsql.ISplitSQL;
import com.sunmnet.pub.db.splitsql.impl.SplitMySql;
import com.sunmnet.pub.db.splitsql.impl.SplitOracle;
import com.sunmnet.pub.db.splitsql.impl.SplitSybase;
import com.sunmnet.pub.db.template.Template;
import com.sunmnet.pub.db.template.envm.Placeholders;
import com.sunmnet.pub.db.template.envm.TemplateFiles;
import com.sunmnet.util.io.FileUtils;
import com.sunmnet.util.lang.StringUtils;

/**
 * 数据库工具类,DB类的辅助类,为DB类提供数据库执行方法
 * 
 */
public class DBTools {

	/**
	 * java关键数组
	 */
	private final static String[] JAVA_KEY_WORDS = {
			"abstract", "assert", "boolean", "break", "byte",
			"case", "catch", "char", "class", "const",
			"continue", "default", "do", "double", "else",
			"enum", "extends", "final", "finally", "float",
			"for", "goto", "if", "implements", "import",
			"instanceof", "int", "interface", "long", "native",
			"new", "package", "private", "protected", "public",
			"return", "short", "static", "strictfp", "super",
			"switch", "synchronized", "this", "throw", "throws",
			"transient", "try", "void", "volatile", "while",	
	};
	
	/**
	 * java关键字列表
	 */
	private final static List<String> JAVA_KEY_WORD_LIST = 
			strArray2List(JAVA_KEY_WORDS);

	/**
	 * 使用getBeanFromDB或getBeanFromPDM时，
	 * 若需要删除表名前缀的规范部分（如"T_","T_ZHWG_"等），可把该前缀配置到这里。
	 * 移除前缀有先后，首先匹配到的前缀先移除，其后的前缀不再执行移除
	 */
	private static List<String> removeTablePres = new LinkedList<String>();
	
	/**
	 * 增加一个要移除的表前缀，配合 getBeanFromDB 或 getBeanFromPDM 方法使用
	 * @param tablePre 前缀
	 */
	@Deprecated
	public static void addRemoveTablePre(String tablePre) {
		DBTools.removeTablePres.add(tablePre);
	}
	
	/**
	 * 增加多个要移除的表前缀，配合 getBeanFromDB 或 getBeanFromPDM 方法使用
	 * @param tablePres 前缀
	 */
	@Deprecated
	public static void addRemoveTablePre(String[] tablePres) {
		for(String tablePre : tablePres) {
			DBTools.removeTablePres.add(tablePre);
		}
	}
	
	/**
	 * 把要移除的前缀从表前缀列表中删除，配合 getBeanFromDB 或 getBeanFromPDM 方法使用
	 * @param tablePre 前缀
	 */
	@Deprecated
	public static void delRemoveTablePre(String tablePre) {
		DBTools.removeTablePres.remove(tablePre);
	}
	
	/**
	 * 从数据库中的表信息创建javabean
	 * 
	 * @param conn 数据库连接
	 * @param packageName 导出实体类所在的包名,如：com.catt.pub.db.bean
	 * @param expPath 导出实体类的路径,如：./src/main/java/com/catt/pub/db/bean
	 * @param tableList 选择要导出的表，为空则导出所有表
	 * @throws SQLException 连接数据库异常
	 * @throws IOException IO异常
	 */
	public static void getBeanFromDB(Connection conn, String packageName,
			String expPath, List<String> tableList) 
					throws SQLException, IOException {
		String[] tableArray = strList2Array(tableList);
		String[] tablePreArray = null;
		getBeanFromDB(conn, packageName, expPath, tableArray, tablePreArray);
	}
	
	/**
	 * 从数据库中的表信息创建javabean
	 * 
	 * @param conn 数据库连接
	 * @param packageName 导出实体类所在的包名,如：com.catt.pub.db.bean
	 * @param expPath 导出实体类的路径,如：./src/main/java/com/catt/pub/db/bean
	 * @param tableList 选择要导出的表，为空则导出所有表
	 * @param tablePreList 希望移除的（多个）表前缀
	 * @throws SQLException 连接数据库异常
	 * @throws IOException IO异常
	 */
	public static void getBeanFromDB(Connection conn, String packageName,
			String expPath, List<String> tableList, List<String> tablePreList) 
					throws SQLException, IOException {
		String[] tableArray = strList2Array(tableList);
		String[] tablePreArray = strList2Array(tablePreList);
		getBeanFromDB(conn, packageName, expPath, tableArray, tablePreArray);
	}
	
	/**
	 * 从数据库中的表信息创建javabean
	 * 
	 * @param conn 数据库连接
	 * @param packageName 导出实体类所在的包名,如：com.catt.pub.db.bean
	 * @param expPath 导出实体类的路径,如：./src/main/java/com/catt/pub/db/bean
	 * @param tableList 选择要导出的表，为空则导出所有表
	 * @param tablePreArray 希望移除的（多个）表前缀
	 * @throws SQLException 连接数据库异常
	 * @throws IOException IO异常
	 */
	public static void getBeanFromDB(Connection conn, String packageName,
			String expPath, List<String> tableList, String[] tablePreArray) 
					throws SQLException, IOException {
		String[] tableArray = strList2Array(tableList);
		getBeanFromDB(conn, packageName, expPath, tableArray, tablePreArray);
	}
	
	/**
	 * 从数据库中的表信息创建javabean
	 * 
	 * @param conn 数据库连接
	 * @param packageName 导出实体类所在的包名,如：com.catt.pub.db.bean
	 * @param expPath 导出实体类的路径,如：./src/main/java/com/catt/pub/db/bean
	 * @param tableArray 选择要导出的表，为空则导出所有表
	 * @throws SQLException 连接数据库异常
	 * @throws IOException IO异常
	 */
	public static void getBeanFromDB(Connection conn, String packageName,
			String expPath, String[] tableArray) 
					throws SQLException, IOException {
		String[] tablePreArray = null;
		getBeanFromDB(conn, packageName, expPath, tableArray, tablePreArray);
	}
	
	/**
	 * 从数据库中的表信息创建javabean
	 * 
	 * @param conn 数据库连接
	 * @param packageName 导出实体类所在的包名,如：com.catt.pub.db.bean
	 * @param expPath 导出实体类的路径,如：./src/main/java/com/catt/pub/db/bean
	 * @param tableArray 选择要导出的表，为空则导出所有表
	 * @param tablePreList 希望移除的（多个）表前缀
	 * @throws SQLException 连接数据库异常
	 * @throws IOException IO异常
	 */
	public static void getBeanFromDB(Connection conn, String packageName,
			String expPath, String[] tableArray, List<String> tablePreList) 
					throws SQLException, IOException {
		String[] tablePreArray = strList2Array(tablePreList);
		getBeanFromDB(conn, packageName, expPath, tableArray, tablePreArray);
	}
	
	/**
	 * 从数据库中的表信息创建javabean
	 * 
	 * @param conn 数据库连接
	 * @param packageName 导出实体类所在的包名,如：com.catt.pub.db.bean
	 * @param expPath 导出实体类的路径,如：./src/main/java/com/catt/pub/db/bean
	 * @param tableArray 选择要导出的表，为空则导出所有表
	 * @param tablePreArray 希望移除的（多个）表前缀
	 * @throws SQLException 连接数据库异常
	 * @throws IOException IO异常
	 */
	public static void getBeanFromDB(Connection conn, String packageName,
			String expPath, String[] tableArray, String[] tablePreArray) 
					throws SQLException, IOException {
		
		List<String> tableList = (
				(tableArray == null || tableArray.length == 0) ? 
				null : strArray2List(tableArray));
		List<String> tablePreList = (
				(tablePreArray == null || tablePreArray.length == 0) ? 
				DBTools.removeTablePres : strArray2List(tablePreArray));
		
		DatabaseMetaData dmd = conn.getMetaData();
		ResultSet tableInfos = checkDBType(dmd);
		
		//迭代所有表，选择需要生成bean的表进行处理
		while (tableInfos.next()) {
			String tableName = tableInfos.getObject("TABLE_NAME").toString();
			if (tableName.toLowerCase().indexOf("bin$") != -1) {
				continue;
			}
			if (tableList != null && !tableList.contains(tableName)) {
				continue;
			}
			
			List<String> colNameList = new LinkedList<String>();//列名表
			Map<String, String> colTypeMap = 					//列名 - java类型
					new HashMap<String, String>();
			
			ResultSet colInfos = checkColumnsType(dmd, tableName);
			while (colInfos.next()) {
				String colType = dataBaseToJavaType(
						colInfos.getString("TYPE_NAME"));
				String colName = colInfos.getString(4);
				
				colNameList.add(colName);
				colTypeMap.put(colName, colType);
			}
			
			//获取主键列名
			String pkColumnName = "";
			ResultSet pkRS = dmd.getPrimaryKeys(null, null, tableName);
			if(pkRS.next()) {
				pkColumnName = (String) pkRS.getObject(4);
			}
			
			//生成Bean内容
			String expData = createBeanData(tableName, colNameList, colTypeMap,
					pkColumnName, packageName, tablePreList);
			
			//生成bean类文件
			String expFilePath = expPath + 
					"/" + getHumpTableName(tableName, tablePreList) + ".java";
			File expFile = FileUtils.createFile(expFilePath);
			FileUtils.write(expFile, expData, 
					Template.DEFAULT_CHARSET, false);
		}
	}
	
	/**
	 * 从PDM文件解析表信息创建javabean
	 * 
	 * @param pdmPath PDM文件所在路径
	 * @param packageName 导出实体类所在的包名,如：com.catt.pub.db.bean
	 * @param expPath 导出实体类的路径,如：./src/main/java/com/catt/pub/db/bean
	 * @param tableList 选择要导出的表，为空则导出所有表
	 * @throws IOException IO异常
	 */
	public static void getBeanFromPDM(String pdmPath, String packageName,
			String expPath, List<String> tableList) throws IOException {
		String[] tableArray = strList2Array(tableList);
		String[] tablePreArray = null;
		getBeanFromPDM(pdmPath, packageName, expPath, 
				tableArray, tablePreArray);
	}
	
	/**
	 * 从PDM文件解析表信息创建javabean
	 * 
	 * @param pdmPath PDM文件所在路径
	 * @param packageName 导出实体类所在的包名,如：com.catt.pub.db.bean
	 * @param expPath 导出实体类的路径,如：./src/main/java/com/catt/pub/db/bean
	 * @param tableList 选择要导出的表，为空则导出所有表
	 * @param tablePreList 希望移除的（多个）表前缀
	 * @throws IOException IO异常
	 */
	public static void getBeanFromPDM(String pdmPath, String packageName,
			String expPath, List<String> tableList, 
			List<String> tablePreList) throws IOException {
		String[] tableArray = strList2Array(tableList);
		String[] tablePreArray = strList2Array(tablePreList);
		getBeanFromPDM(pdmPath, packageName, expPath, 
				tableArray, tablePreArray);
	}
	
	/**
	 * 从PDM文件解析表信息创建javabean
	 * 
	 * @param pdmPath PDM文件所在路径
	 * @param packageName 导出实体类所在的包名,如：com.catt.pub.db.bean
	 * @param expPath 导出实体类的路径,如：./src/main/java/com/catt/pub/db/bean
	 * @param tableList 选择要导出的表，为空则导出所有表
	 * @param tablePreArray 希望移除的（多个）表前缀
	 * @throws IOException IO异常
	 */
	public static void getBeanFromPDM(String pdmPath, String packageName,
			String expPath, List<String> tableList, 
			String[] tablePreArray) throws IOException {
		String[] tableArray = strList2Array(tableList);
		getBeanFromPDM(pdmPath, packageName, expPath, 
				tableArray, tablePreArray);
	}
	
	/**
	 * 从PDM文件解析表信息创建javabean
	 * 
	 * @param pdmPath PDM文件所在路径
	 * @param packageName 导出实体类所在的包名,如：com.catt.pub.db.bean
	 * @param expPath 导出实体类的路径,如：./src/main/java/com/catt/pub/db/bean
	 * @param tableArray 选择要导出的表，为空则导出所有表
	 * @throws IOException IO异常
	 */
	public static void getBeanFromPDM(String pdmPath, String packageName,
			String expPath, String[] tableArray) throws IOException {
		String[] tablePreArray = null;
		getBeanFromPDM(pdmPath, packageName, expPath, 
				tableArray, tablePreArray);
	}
	
	/**
	 * 从PDM文件解析表信息创建javabean
	 * 
	 * @param pdmPath PDM文件所在路径
	 * @param packageName 导出实体类所在的包名,如：com.catt.pub.db.bean
	 * @param expPath 导出实体类的路径,如：./src/main/java/com/catt/pub/db/bean
	 * @param tableArray 选择要导出的表，为空则导出所有表
	 * @param tablePreList 希望移除的（多个）表前缀
	 * @throws IOException IO异常
	 */
	public static void getBeanFromPDM(String pdmPath, String packageName,
			String expPath, String[] tableArray, 
			List<String> tablePreList) throws IOException {
		String[] tablePreArray = strList2Array(tablePreList);
		getBeanFromPDM(pdmPath, packageName, expPath, 
				tableArray, tablePreArray);
	}
	
	/**
	 * 从PDM文件解析表信息创建javabean
	 * 
	 * @param pdmPath PDM文件所在路径
	 * @param packageName 导出实体类所在的包名,如：com.catt.pub.db.bean
	 * @param expPath 导出实体类的路径,如：./src/main/java/com/catt/pub/db/bean
	 * @param tableArray 选择要导出的表，为空则导出所有表
	 * @param tablePreArray 希望移除的（多个）表前缀
	 * @throws IOException IO异常
	 */
	@SuppressWarnings("unchecked")
	public static void getBeanFromPDM(String pdmPath, String packageName,
			String expPath, String[] tableArray, 
			String[] tablePreArray) throws IOException {
		
		List<String> tableList = (
				(tableArray == null || tableArray.length == 0) ? 
				null : strArray2List(tableArray));
		List<String> tablePreList = (
				(tablePreArray == null || tablePreArray.length == 0) ? 
				DBTools.removeTablePres : strArray2List(tablePreArray));
		
		List<PdmTable> pdmTableList = new ArrayList<PdmTable>();
		Map<String, String> xmlnsMap = new HashMap<String, String>();
		xmlnsMap.put("o", "object");
		SAXReader saxReader = new SAXReader();
		Reader reader = null;
		Document document = null;
		
		try {
			reader = new InputStreamReader(
					new FileInputStream(pdmPath), "UTF-8");
			document = saxReader.read(reader);
		} catch (Exception e) {
			e.printStackTrace();
		}
		XPath x = document.createXPath("//o:Table"); // 用XPath解析
		x.setNamespaceURIs(xmlnsMap);
		List<Element> elms = x.selectNodes(document);

		//析取所有表对象
		for (Iterator<Element> elmIts = elms.iterator(); elmIts.hasNext();) {
			Element tableElm = elmIts.next();
			PdmTable pdmTable = new PdmTable();
			pdmTable.setTableName(tableElm.elementText("Code"));
			
			System.out.println("+++++++++++++++++++");
			System.out.println(tableElm.elementText("Code"));
			
			for (Iterator<Element> innerChild = tableElm.elementIterator(); 
					innerChild.hasNext();) {
				Element elements = innerChild.next();
				pdmTable = getElementList(pdmTable, elements);
				pdmTableList.add(pdmTable);
			}
		}
		
		//迭代所有表，选择需要生成bean的表进行处理
		for (Iterator<PdmTable> iter = pdmTableList.iterator(); 
				iter.hasNext();) {
			PdmTable pdmTable = (PdmTable) iter.next();
			String tableName = pdmTable.getTableName().toString();
			
			if (tableList != null && !tableList.contains(tableName)) {
				continue;
			}

			List<String> colNameList = new LinkedList<String>();//列名表
			Map<String, String> colTypeMap = 					//列名 - java类型
					new HashMap<String, String>();
			
			List<PdmColumn> pdmCols = pdmTable.getColumnList();
			for (Iterator<PdmColumn> colIts = pdmCols.iterator(); 
					colIts.hasNext();) {
				PdmColumn pdmCol = colIts.next();
				String colName = pdmCol.getColumn();
				String colType = pdmCol.getColumnType();
				
				colNameList.add(colName);
				colTypeMap.put(colName, colType);
			}
			
			//获取主键列名(暂未有获取pdm文件主键的方法)
			String pkColumnName = "";
			
			//生成Bean内容
			String expData = createBeanData(tableName, colNameList, colTypeMap,
					pkColumnName, packageName, tablePreList);
			
			//生成bean类文件
			String expFilePath = expPath + 
					"/" + getHumpTableName(tableName, tablePreList) + ".java";
			System.out.println(expFilePath);
			File expFile = FileUtils.createFile(expFilePath);
			FileUtils.write(expFile, expData, 
					Template.DEFAULT_CHARSET, false);
		}
	}
	
	/**
	 * 根据模板生成bean类的内容。
	 * 
	 * @param tableName 表名
	 * @param colNameList 表的列名集
	 * @param colTypeMap 每个列对应的类型映射表
	 * @param pkColumnName 主键列名,根据是否为空影响update语句
	 * @param packageName 类所属的包名
	 * @param tablePreList 去除表前缀的规范前缀表
	 * @return bean类的内容
	 */
	private static String createBeanData(String tableName, 
			List<String> colNameList, Map<String, String> colTypeMap, 
			String pkColumnName, String packageName, 
			List<String> tablePreList) {
		StringBuilder sb = new StringBuilder();
		int colNum = colNameList.size();	//列数
		
		//取类模板
		Template beanClazz = new Template();
		beanClazz.read(TemplateFiles.bean_template);
		
		//设置年份和日期
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String date = sdf.format(new Date());
		beanClazz.set(Placeholders.year, date.substring(0, 4));
		beanClazz.set(Placeholders.date, date);
		
		//设置包路径
		beanClazz.set(Placeholders.package_path, packageName);
		
		//设置类名：去前缀的驼峰表名
		String clazzName = getHumpTableName(tableName, tablePreList);
		beanClazz.set(Placeholders.class_name, clazzName);
		
		//设置成员变量
		sb.setLength(0);
		for(String colName : colNameList) {
			String colType = colTypeMap.get(colName);
			String humpColName = getHumpColumnName(colName, false);
			sb.append("    /** ").append(colName).append(" */\r\n");
			sb.append("    private ").append(colType).append(" ");
			sb.append(humpColName).append(";\r\n\r\n");
		}
		sb.setLength(sb.length() - 2);	//移除最后一个 "\r\n"
		beanClazz.set(Placeholders.class_member, sb.toString());

		//设置getter setter
		sb.setLength(0);
		for(String colName : colNameList) {
			String colType = colTypeMap.get(colName);
			String uppHumpColName = getHumpColumnName(colName, true);
			String lowHumpColName = getHumpColumnName(colName, false);
			
			//getter
			sb.append("    /**\r\n");
			sb.append("     * get").append(uppHumpColName).append("\r\n");
			sb.append("     * @return ").append(colType).append("\r\n");
			sb.append("     */\r\n");
			sb.append("    public ").append(colType);
			sb.append(" get").append(uppHumpColName).append("() {\r\n");
			sb.append("        return this.").append(lowHumpColName);
			sb.append(";\r\n    }\r\n\r\n");
			
			//setter
			sb.append("    /**\r\n");
			sb.append("     * set").append(uppHumpColName).append("\r\n");
			sb.append("     * @param ").append(lowHumpColName);
			sb.append(" ").append(lowHumpColName).append(" to set\r\n");
			sb.append("     */\r\n");
			sb.append("    public void");
			sb.append(" set").append(uppHumpColName);
			sb.append("(").append(colType).append(" ");
			sb.append(lowHumpColName).append(") {\r\n");
			sb.append("        this.").append(lowHumpColName).append(" = ");
			sb.append(lowHumpColName).append(";\r\n    }\r\n\r\n");
		}
		sb.setLength(sb.length() - 2);	//移除最后一个 "\r\n"
		beanClazz.set(Placeholders.getter_and_setter, sb.toString());
		
		//设置表名
		beanClazz.set(Placeholders.table_name, tableName);
		
		//设置insert列
		sb.setLength(0);
		for(String colName : colNameList) {
			sb.append(colName).append(", ");
		}
		sb.setLength(sb.length() - 2);	//移除最后一个 ", "
		beanClazz.set(Placeholders.insert_column, sb.toString());
		
		//设置insert占位符
		sb.setLength(0);
		for(int i = 0; i < colNum; i++) {
			sb.append("?, ");
		}
		sb.setLength(sb.length() - 2);	//移除最后一个 ", "
		beanClazz.set(Placeholders.insert_column_placeholder, sb.toString());
		
		//设置update列
		sb.setLength(0);
		for(String colName : colNameList) {
			if(colNum > 1 && //当只有1列时，不做主键判断
					pkColumnName != null && !"".equals(pkColumnName)) { //不update主键
				if(pkColumnName.equals(colName)) {
					continue;
				}
			}
			sb.append(colName).append(" = ?, ");
		}
		sb.setLength(sb.length() - 2);	//移除最后一个 ", "
		beanClazz.set(Placeholders.update_column, sb.toString());
		
		//设置select列
		sb.setLength(0);
		for(String colName : colNameList) {
			String lowHumpColName = getHumpColumnName(colName, false);
			
			sb.append(colName).append(" AS \\\"");
			sb.append(lowHumpColName).append("\\\", ");
		}
		sb.setLength(sb.length() - 2);	//移除最后一个 ", "
		beanClazz.set(Placeholders.select_column, sb.toString());
		
		//设置 insert用于替换占位符的参数 
		sb.setLength(0);
		for(String colName : colNameList) {
			String uppHumpColName = getHumpColumnName(colName, true);
			
			sb.append("                bean.get").append(uppHumpColName);
			sb.append("(),\r\n");
		}
		sb.setLength(sb.length() - 3);	//移除最后一个 ",\r\n"
		beanClazz.set(Placeholders.insert_params, sb.toString());
		
		//设置 update用于替换占位符的参数 
		sb.setLength(0);
		for(String colName : colNameList) {
			if(colNum > 1 && //当只有1列时，不做主键判断
					pkColumnName != null && !"".equals(pkColumnName)) { //不update主键
				if(pkColumnName.equals(colName)) {
					continue;
				}
			}
			String uppHumpColName = getHumpColumnName(colName, true);
			
			sb.append("                bean.get").append(uppHumpColName);
			sb.append("(),\r\n");
		}
		sb.setLength(sb.length() - 3);	//移除最后一个 ",\r\n"
		beanClazz.set(Placeholders.update_params, sb.toString());
		
		//设置 获取单个数据库字段域名称的方法
		sb.setLength(0);
		for(String colName : colNameList) {
			String uppHumpColName = getHumpColumnName(colName, true);
			
			sb.append("    /**\r\n");
			sb.append("     * get column name\r\n");
			sb.append("     * @return ").append(colName).append("\r\n");
			sb.append("     */\r\n");
			sb.append("    public static String get").append(uppHumpColName);
			sb.append("$ColName() {\r\n");
			sb.append("        return \"").append(colName);
			sb.append("\";\r\n    }\r\n\r\n");
		}
		sb.setLength(sb.length() - 2);	//移除最后一个 "\r\n"
		beanClazz.set(Placeholders.get_column_name, sb.toString());
		
		//设置 获取单个类成员变量名称的方法
		sb.setLength(0);
		for(String colName : colNameList) {
			String uppHumpColName = getHumpColumnName(colName, true);
			String lowHumpColName = getHumpColumnName(colName, false);
			
			sb.append("    /**\r\n");
			sb.append("     * get java name\r\n");
			sb.append("     * @return ").append(lowHumpColName);
			sb.append("\r\n     */\r\n");
			sb.append("    public static String get").append(uppHumpColName);
			sb.append("$JavaName() {\r\n");
			sb.append("        return \"").append(lowHumpColName);
			sb.append("\";\r\n    }\r\n\r\n");
		}
		sb.setLength(sb.length() - 2);	//移除最后一个 "\r\n"
		beanClazz.set(Placeholders.get_java_name, sb.toString());
		
		//设置 获取所有数据库字段域名称的方法
		sb.setLength(0);
		for(String colName : colNameList) {
			sb.append(colName).append(", ");
		}
		sb.setLength(sb.length() - 2);	//移除最后一个 ", "
		beanClazz.set(Placeholders.all_column_names, sb.toString());
		
		//设置 获取所有类成员变量名称的方法
		sb.setLength(0);
		for(String colName : colNameList) {
			String lowHumpColName = getHumpColumnName(colName, false);
			sb.append(lowHumpColName).append(", ");
		}
		sb.setLength(sb.length() - 2);	//移除最后一个 ", "
		beanClazz.set(Placeholders.all_java_names, sb.toString());
		
		//设置 toString方法
		sb.setLength(0);
		for(String colName : colNameList) {
			String uppHumpColName = getHumpColumnName(colName, true);
			String lowHumpColName = getHumpColumnName(colName, false);
			
			sb.append("        sb.append(\"\\t").append(colName);
			sb.append('/').append(lowHumpColName).append("\").append(");
			sb.append("\" = \").append(this.get");
			sb.append(uppHumpColName).append("()).append(\"\\r\\n\");");
			sb.append("\r\n");
		}
		sb.setLength(sb.length() - 2);	//移除最后一个 "\r\n"
		beanClazz.set(Placeholders.to_string, sb.toString());
		
		//模板占位符替换完成，返回替换内容
		return beanClazz.getContent();
	}
	
	/**
	 * 把含下划线的表名构造为驼峰结构，并剔除诸如以"T_ZHWG_"或"T_"开头的规范部分(需配置,默认不剔除).
	 * 不带下划线的表名,剔除前缀并将首字母大写后返回.
	 * 
	 * 若处理完得到的名称是java关键字，则前面补 $
	 * 
	 * @param tableName 原表名
	 * @param tablePreList 希望移除表名开头的规范部分内容。可传入多个判定式，但仅匹配第1个
	 * @return 若表名不含下划线则原样返回；否则返回驼峰结构的表名
	 */
	private static String getHumpTableName(
			String tableName, List<String> tablePreList) {
		String tmpName = tableName;
		
		//含下划线的表名
		if(tmpName != null && tmpName.contains("_")) {
			StringBuffer sb = new StringBuffer();
			
			//若表名以下划线开头，剔除之
			while(tmpName.startsWith("_")) {
				tmpName = tmpName.substring(1);
			}
			
			//若表名以下划线结尾，剔除之，防止下面操作数组越界
			while(tmpName.endsWith("_")) {
				tmpName = tmpName.substring(0, tmpName.length() - 1);
			}
			
			//剔除表名开头的规范部分
			for(String str : tablePreList) {
				if(tmpName.startsWith(str)) {
					tmpName = tmpName.substring(str.length());
					break;
				}
			}
			
			//若表名以下划线开头，剔除之
			while(tmpName.startsWith("_")) {
				tmpName = tmpName.substring(1);
			}
			
			tmpName = tmpName.toLowerCase();
			char[] charArray = tmpName.toCharArray();
			sb.append((char) (charArray[0] - 32));	//表名首字母大写
			
			//把下划线删除，其后的字母转为大写
			for(int i = 1; i < charArray.length; i++) {
				if(charArray[i] == '_') {
					i++;
					sb.append((char) (charArray[i] - 32));
				} else {
					sb.append(charArray[i]);
				}
			}
			tmpName = sb.toString();
			
		//不含下划线的表名
		} else {
			
			//剔除表名开头的规范部分
			for(String str : tablePreList) {
				if(tmpName.startsWith(str)) {
					tmpName = tmpName.substring(str.length());
					break;
				}
			}
			
			//首字母大写
			tmpName = firstWordToUpp(tmpName);
		}
		
		if(true == isJavaKeyWord(tmpName)) {
			tmpName = "$" + tmpName;
		}
		return tmpName;
	}
	
	/**
	 * 把含下划线的列名构造为驼峰结构.
	 * 不带下划线的列名则只改变首字母大小写.
	 * 
	 * 若处理完得到的名称是java关键字，则前面补 _
	 * 
	 * @param columnName 列名
	 * @param firstUpper 开头字母是否需要大写
	 * @return 驼峰形式列名
	 */
	private static String getHumpColumnName(
			String columnName, boolean firstUpper) {
		String tmpName = columnName;
		
		//含下划线的列名
		if(tmpName != null && tmpName.contains("_")) {
			StringBuilder sb = new StringBuilder();
			
			//若列名以下划开头，剔除之
			while(tmpName.startsWith("_")) {
				tmpName = tmpName.substring(1);
			}
			
			//删除字段类型前缀 I_ 、 S_ 、D_ 等
			if(tmpName.charAt(1) == '_') {
				tmpName = tmpName.substring(2);
			}
			
			//若列名以下划结尾，剔除之，防止下面操作数组越界
			while(tmpName.endsWith("_")) {
				tmpName = tmpName.substring(0, tmpName.length() - 1);
			}
			
			tmpName = tmpName.toLowerCase();
			char[] charArray = tmpName.toCharArray();
			
			//首字母大写
			if(firstUpper == true) {
				sb.append((char) (charArray[0] - 32));
				
			//首字母小写
			} else {
				sb.append(charArray[0]);	
			}
			
			//把下划线删除，其后的字母转为大写
			for(int i = 1; i < charArray.length; i++) {
				if(charArray[i] == '_') {
					i++;
					sb.append((char) (charArray[i] - 32));
				} else {
					sb.append(charArray[i]);
				}
			}
			tmpName = sb.toString();
			
		//不含下划线的列名
		} else {
			if(firstUpper == true) {
				tmpName = firstWordToUpp(tmpName);
			} else {
				tmpName = firstWordToLow(tmpName);
			}
		}
		
		if(true == isJavaKeyWord(tmpName)) {
			tmpName = "_" + tmpName;
		}
		return tmpName;
	}
	
	/**
	 * 判断数据库类型
	 * 
	 * @param dmd
	 *            DatabaseMetaData对象
	 * @return ResultSet ResultSet对象
	 * @throws SQLException 获取不到数据库类型
	 */
	private static ResultSet checkDBType(DatabaseMetaData dmd)
			throws SQLException {
		String types[] = { "TABLE" };
		String dbName = dmd.getDatabaseProductName();
		ResultSet tabs = null;

		if (dbName.toLowerCase().equals("oracle")) {
			tabs = dmd.getTables(null, dmd.getUserName().toUpperCase(), null,
					types);
		} else if (dbName.toLowerCase().equals("mysql")) {
			tabs = dmd.getTables(null, null, null, types);
		} else if (dbName.equals("Adaptive Server Enterprise")) {
			tabs = dmd.getTables(null, null, null, types);
		} else if (dbName.toLowerCase().equals("sqlserver")) {
			tabs = dmd.getTables(null, null, null, types);
		}
		return tabs;
	}
	
	/**
	 * 检查每列
	 * 
	 * @param dmd
	 *            DatabaseMetaData对象
	 * @param tblName
	 *            表名
	 * @return ResultSet集合
	 * @throws SQLException 获取不到数据名 
	 */
	private static ResultSet checkColumnsType(DatabaseMetaData dmd,
			String tblName) throws SQLException {
		String dbName = dmd.getDatabaseProductName();
		ResultSet tabs = null;

		if (dbName.toLowerCase().equals("oracle")) {
			tabs = dmd.getColumns(null, dmd.getUserName().toUpperCase(),
					tblName, null);
		} else if (dbName.toLowerCase().equals("mysql")) {
			tabs = dmd.getColumns(null, "%", tblName, "%");
		} else if (dbName.equals("Adaptive Server Enterprise")) {
			tabs = dmd.getColumns(null, null, tblName, null);
		}
		return tabs;
	}
	
	/**
	 * 返回封装了数据的PdmTable
	 * @param pdmTable PdmTable对象
	 * @param elements Element元素
	 * @return 封装了数据的PdmTable
	 */
	@SuppressWarnings("unchecked")
	public static PdmTable getElementList(PdmTable pdmTable, Element elements){
		if (elements.getName().equals("Columns")) { // 获取列集合
			List<PdmColumn> columnList = new ArrayList<PdmColumn>();

			for (Iterator<Element> columnChild = elements
					.elementIterator(); columnChild.hasNext();) {
				Element columns = columnChild.next();
				PdmColumn column2 = new PdmColumn();
				
				System.out.println("******************************");
				System.out.println(columns.elementText("Code"));
				System.out.println(columns.elementText("Name"));
				System.out.println(columns.elementText("DataType"));
				
				column2.setColumn(columns.elementText("Code"));
				column2.setColumnName(columns.elementText("Name"));
				column2.setColumnType(dataBaseToJavaType(columns.elementText("DataType")));
				column2.setComment(columns.elementText("Comment"));
				columnList.add(column2);
			}
			pdmTable.setColumnList(columnList);
		}
		return pdmTable;
	}
	
	/**
	 * 数据库的数据类型转换java 数据类型
	 * 
	 * @param source
	 *            数据库的数据类型
	 * @return java 数据类型
	 */
	private static String dataBaseToJavaType(String source) {
		String result = null;
		source = source.toLowerCase();

		if (source.equals("float")) {
			result = "float";
		} else if (source.startsWith("varchar") 
				|| source.startsWith("char")
				|| source.startsWith("varchar2") 
				|| source.startsWith("long")
				|| source.startsWith("longtext") 
				|| source.startsWith("text")
				|| "enum".equals(source)) {
			result = "String";
		} else if (source.equals("int") 
				|| source.equals("smallint")
				|| source.equals("mediumint") 
				|| source.equals("tinyint")) {
			result = "Integer";
		} else if (source.startsWith("number") 
				|| source.startsWith("numeric")) {
			result = "Long";
		} else if (source.equals("date")) {
			result = "java.util.Date";
		} else if (source.equals("time")) {
			result = "java.sql.Time";
		} else if (source.equals("datetime") 
				|| source.startsWith("timestamp")) {
			result = "java.sql.Timestamp";
		} else if (source.equals("double")) {
			result = "Double";
		} else if (source.equals("numeric")) {
			result = "BigDecimal";
		} else if (source.equals("bigint")) {
			result = "java.math.BigInteger";
		} else if (source.equals("decimal")) {
			result = "java.math.BigDecimal";
		} else if (source.equals("blob")) {
			result = "blob";
		} else if ("clob".equals(source)) {
			result = "clob";
		} 
		if(checkNotNull(result)){
			return result;
		}else{
			throw new NoConfException("后台暂不支持该数据库类型转换成对应的java数据类型:" + source);
		}

	}

	/**
	 * 判断URL是否存在，如果不存在则拼装
	 * @param ds DataSourceBean对象
	 * @return 拼装URL
	 */
	public static String initURL(DataSourceBean ds) {
		String url = null;

		if (checkNotNull(ds.getUrl())) {
			url = ds.getUrl();
		} else {
			if(ds.getDriver().contains("cattDriver")){
				String subDriver = ds.getDriver().split("\\.")[1];
				
				if (subDriver.contains("mysql")) {
					url = "cattproxy:jdbc:mysql://" + ds.getIp() + ":" + ds.getPort() + "/"
							+ ds.getDbname();
					String charSet = ds.getCharset();
					String str = checkNotNull(charSet) ? charSet : "UTF-8";
					url += "?autoReconnect=true&useUnicode=true" +
							"&characterEncoding=" + str; 	//数据库编码，应与数据库一致
//							"&characterSetResults=" + str;	//返回结果集编码，应与程序一致
					
				} else if (subDriver.contains("oracle")) {
					url = "cattproxy:jdbc:oracle:thin:@" + ds.getIp() + ":" + 
							ds.getPort() + ":" + ds.getDbname();
					
				} else if (subDriver.contains("sybase")) {
					String charset = ds.getCharset();
					if (StringUtils.isEmpty(charset) 
							|| "UTF-8".equalsIgnoreCase(charset)
							|| "GBK".equalsIgnoreCase(charset)
							|| "GB2312".equalsIgnoreCase(charset)) {
						charset = "cp936";
					}
					url = "cattproxy:jdbc:sybase:Tds:" + ds.getIp() + ":" + 
							ds.getPort() + "/" + ds.getDbname() + 
							"?charset=" + charset + 
							"&jconnect_version=" + ds.getJconnectVersion();
					
				} else if (subDriver.contains("sqlserver")) { //com.microsoft.jdbc.sqlserver.SQLServerDriver
					url = "cattproxy:jdbc:microsoft:sqlserver://" + 
							ds.getIp() + ":" + ds.getPort() + 
							";DatabaseName=" + ds.getDbname();
					
				} else if (subDriver.contains("postgresql")) {
		            url = "cattproxy:jdbc:postgresql://" + ds.getIp() + ":" + 
		            		ds.getPort() + "/" + ds.getDbname();
		            
				} else if(ds.getDriver().contains("access")){
					url = "cattproxy:jdbc:rmi://" + ds.getIp() + 
							"/jdbc:odbc:" + ds.getDbname();
				}
				ds.setDriver("com.catt.pub.db.jdbc.CattDriver");
				
			}else if (ds.getDriver().contains("mysql")) {
//				jdbc:mysql://172.168.10.95:3306/analyser?user=root&password=root
//				&autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
//				&zeroDateTimeBehavior=convertToNull
//				参数参考：http://elf8848.iteye.com/blog/1684414
				url = "jdbc:mysql://" + ds.getIp() + ":" + ds.getPort() + "/"
						+ ds.getDbname();
				String charSet = ds.getCharset();
				String str = checkNotNull(charSet) ? charSet : "UTF-8";
				url += "?autoReconnect=true&useUnicode=true" +
						"&zeroDateTimeBehavior=convertToNull&characterEncoding=" + str; 	
//						"&characterSetResults=" + str;	//返回结果集编码，应与程序一致
				
			} else if (ds.getDriver().contains("oracle")) {
				url = "jdbc:oracle:thin:@" + ds.getIp() + ":" + 
						ds.getPort() + ":" + ds.getDbname();
				
			} else if (ds.getDriver().contains("sybase")) {
				String charset = ds.getCharset();
				if (StringUtils.isEmpty(charset) 
						|| "UTF-8".equalsIgnoreCase(charset)
						|| "GBK".equalsIgnoreCase(charset)
						|| "GB2312".equalsIgnoreCase(charset)) {
					charset = "cp936";
				}
				url = "jdbc:sybase:Tds:" + ds.getIp() + ":" + ds.getPort() + 
						"/" + ds.getDbname() + "?charset=" + charset + 
						"&jconnect_version=" + ds.getJconnectVersion();
				
			} else if (ds.getDriver().contains("sqlserver")) {
				url = "jdbc:microsoft:sqlserver://" + ds.getIp() + ":" + 
						ds.getPort() + ";DatabaseName=" + ds.getDbname();
				
			} else if (ds.getDriver().contains("postgresql")) {
				url = "jdbc:postgresql://" + ds.getIp() + ":" + 
						ds.getPort() + "/" + ds.getDbname();
				
			} else if(ds.getDriver().contains("rmijdbc")){
				url = "jdbc:rmi://" + ds.getIp() + "/jdbc:odbc:" + 
						ds.getDbname();
			} else if(ds.getDriver().contains("informix")){
				/*
				 * jdbc:informix-sqli://[ip]:[port]/[dbName]:informixserver=dbserver;user=[user];password=[pwd]
				 * newlocale=en_us,zh_cn;newcodeset=gbk,8859-1,819;
				 */
				url = "jdbc:informix-sqli://" + ds.getIp() + ":" + ds.getPort() 
						+ "/" + ds.getDbname() + ":informixserver=dbserver;newlocale=en_us,zh_cn"
						+ ";newcodeset=" + ds.getCharset()
						+ ";user=" + ds.getUsername() 
						+ ";password=" + ds.getPassword();
			}
		}
		return url;
	}

	/**
	 * <pre>
	 * SQL脚本执行，目前只支持建表语句, 且语句末尾加;(分号)标识。
	 * 请注意：此方法不做当前要建立的表，存储过程等是否存在做判断。
	 * 默认使用utf-8编码读取文件；
	 * 支持SQLYog和Navicat导出的MYSQL脚本	 
	 * 支持PLSQL导出ORALCE脚本； 
	 * 使用例子：
	 * 		String filePath = "E:\\test2\\table.sql";
	 * 		Connection conn = DBTools.getConnection(ds);
	 * 		DBTools.execSQLFile(conn,filePath);//执行SQL脚本
	 * </pre>
	 * 
	 * @param conn
	 *            连接
	 * @param filePath
	 *            SQL脚本路径
	 * @param batchNum
	 *              批量提交数据的数量，默认是500条提交一次           
	 * @throws IOException 读取不到文件，或文件路径错误
	 * @throws SQLException SQL不能执行
	 * @return 
	 */
	public static int[] execSQLFile(Connection conn, String filePath,
			int batchNum) throws IOException, SQLException {
		String sqls = FileUtils.readFileToString(new File(filePath), "utf-8");
		return execSQLString(conn, sqls, batchNum);
	}

	/**
	 * <PRE>
	 * 执行SQL语句，目前只支持建表语句, 且语句末尾加;
	 * (分号)标识 请注意：此方法不做当前要建立的表，存储过程等是否存在做判断。
	 * </PRE>
	 * @param conn
	 *            连接
	 * @param sqlString
	 *            SQL语句，可以有多条，但必须以;号隔开
	 * @throws SQLException  SQL执行异常
	 * @return
	 */
	@Deprecated
	public static int[] execSQLString2(Connection conn, String sqlString)
			throws SQLException {
		String[] sqls = sqlString.trim().split(";");
		return DBUtils.batchUpdate(conn, sqls);
	}
	
	/**
	 * <PRE>
	 * 执行SQL语句，目前只支持建表语句, 且语句末尾加;(分号)
	 * 支持SQLYog和Navicat工具导出的mysql存储过程、触发器、和函数
	 * 支持PLSQL导出的oracle脚本
	 * 批量提交数据的数量，默认是500条提交一次    
	 * </PRE>
	 * @param conn
	 *            连接
	 * @param sqlString
	 *            SQL语句，可以有多条，但必须以;号隔开
	 * @throws SQLException  SQL执行异常
	 * @return
	 */
	public static int[] execSQLString(Connection conn, String sqlString) 
			throws SQLException {
		return execSQLString(conn, sqlString, 0);
	}
	
	/**
	 * <PRE>
	 * 执行SQL语句，目前只支持建表语句, 且语句末尾加;(分号)
	 * 支持SQLYog和Navicat工具导出的mysql存储过程、触发器、和函数
	 * 支持PLSQL导出的oracle脚本
	 * </PRE>
	 * @param conn
	 *            连接
	 * @param sqlString
	 *            SQL语句，可以有多条，但必须以;号隔开
	 * @param batchNum 批量执行sql语句数
	 * @throws SQLException  SQL执行异常
	 * @return
	 */
	public static int[] execSQLString(Connection conn, String sqlString, 
			int batchNum) throws SQLException {
		DBType type = judgeDBType(conn);
		ISplitSQL split = null;
		switch (type) {
		case MYSQL:
			split = new SplitMySql();
			break;
		case SYBASE:
			split = new SplitSybase();
			break;
		case ORACLE:
			split = new SplitOracle();
			break;
		default:
			break;
		}
		if (split == null) {
			throw new SQLException("不支持数据库类型！");
		}
		
		List<String> list = null;
		if (split.isTrue(sqlString)) {
			list = split.splitSQL(sqlString);
			return DBUtils.batchUpdate(conn, list, batchNum);
		} else {
			throw new SQLException("数据库连接类型和脚本类型不一致！");
		}
	}
	
	/**
	 * 将ResultSet的数据设置到要封装的bean对象属性中
	 * 
	 * @param rs
	 *            查找数据库中clazz类对应的表得到的ResultSet对象
	 * @param clazz
	 *            要装载数据的class
	 * @return 装载了数据的class
	 * 
	 * @throws SQLException
	 *             获取不到连接时抛出
	 * @throws InvocationTargetException
	 *             一种包装由调用方法或构造方法所抛出异常的经过检查的异常
	 * @throws NoSuchMethodException
	 *             无法找到某一特定方法时，抛出该异常
	 * @throws IllegalAccessException
	 *             无法访问指定的类、字段等
	 * @throws InstantiationException
	 *             无法实例化
	 * @throws IllegalArgumentException
	 *             向方法传递了一个不合法或不正确的参数。
	 * @throws SecurityException
	 *             由安全管理器抛出的异常，指示存在安全侵犯。
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static Object getObjectValue(ResultSet rs, Class clazz)
			throws InstantiationException, IllegalAccessException,
			SecurityException, NoSuchMethodException, IllegalArgumentException,
			InvocationTargetException, SQLException {

		// 所有的属性
		Field[] field = clazz.getDeclaredFields();
		Object info = clazz.newInstance();

		for (int i = 0; i < field.length; i++) {

			// 得到属性名
			String name = field[i].getName();

			// 拼装成SetXXX方法
			name = "set" + DBTools.firstWordToUpp(name);

			// 得到类型
			Class c = field[i].getType();
			
			// 得到方法
			Method method = clazz.getMethod(name, c);

			// 实现方法,如果实体类的中有属性为Date类型的,则换种方式转实现
			if (c == Date.class) {
				method.invoke(info, rs.getDate(i + 1));
			} else if (c == Long.class) {
				method.invoke(info, rs.getLong(i + 1));
			} else if (c == String.class) {
				method.invoke(info, rs.getString(i + 1));
			} else if (c == Boolean.class) {
				method.invoke(info, rs.getBoolean(i + 1));
			} else if (c == Double.class) {
				method.invoke(info, rs.getDouble(i + 1));
			} else if (c == Byte.class) {
				method.invoke(info, rs.getByte(i + 1));
			} else if (c == Float.class) {
				method.invoke(info, rs.getFloat(i + 1));
			} else if (c == Integer.class) {
				method.invoke(info, rs.getInt(i + 1));
			} else if (c == BigDecimal.class) {
				method.invoke(info, rs.getBigDecimal(i + 1));
			} else if (c == Blob.class) {
				method.invoke(info, rs.getBlob(i + 1));
			} else if (c == Timestamp.class) {
				method.invoke(info, rs.getTimestamp(i + 1));
			} else if (c == Time.class) {
				method.invoke(info, rs.getTime(i + 1));
			} else {
				//处理简单类型  added by lianghong
				String typeName = c.getName();
				Object o = rs.getObject(i + 1);
				if(typeName.equals("int")){
					if(o instanceof BigDecimal){
						method.invoke(info, ((BigDecimal)o).intValue());
					}else{
						method.invoke(info, o);
					}
				}else if(typeName.equals("long")){
					if(o instanceof BigDecimal){
						method.invoke(info, ((BigDecimal)o).longValue());
					}else{
						method.invoke(info, o);
					}
				}else if(typeName.equals("float")){
					if(o instanceof BigDecimal){
						method.invoke(info, ((BigDecimal)o).floatValue());
					}else{
						method.invoke(info, o);
					}
				}else if(typeName.equals("short")){
					if(o instanceof BigDecimal){
						method.invoke(info, ((BigDecimal)o).shortValue());
					}else{
						method.invoke(info, o);
					}
				}else if(typeName.equals("byte")){
					if(o instanceof BigDecimal){
						method.invoke(info, ((BigDecimal)o).byteValue());
					}else{
						method.invoke(info, o);
					}
				}else if(typeName.equals("double")){
					if(o instanceof BigDecimal){
						method.invoke(info, ((BigDecimal)o).doubleValue());
					}else{
						method.invoke(info, o);
					}
				}else{
					method.invoke(info, o);
				}
				//method.invoke(info, rs.getObject(i + 1));
			}
		}
		return info;
	}
	
	/**
	 * 转换字符串的第一个字母大写
	 * 
	 * @param str 要转换字符串
	 * @return 转换后的结果 ，如： string==>String
	 */
	private static String firstWordToUpp(String str) {
		String first = str.substring(0, 1);
		String suffix = str.substring(1, str.length());
		return first.toUpperCase() + suffix;
	}
	
	/**
	 * 转换字符串的第一个字母为小写
	 * 
	 * @param str 要转换字符串
	 * @return 转换后的结果 ，如： String==>string
	 */
	private static String firstWordToLow(String str) {
		String first = str.substring(0, 1);
		String suffix = str.substring(1, str.length());
		return first.toLowerCase() + suffix;
	}
	
	/**
	 * 判断集合是否为空
	 * 
	 * @param list
	 *            传入的集合
	 * @return true：不空，false：空
	 */
	public static boolean checkNotNull(List<Object> list) {
		return list != null && list.size() > 0;
	}

	/**
	 * 判断字符串是否为空
	 * 
	 * @param param
	 *            传入的字符串
	 * @return true：不空，false：空
	 */
	public static boolean checkNotNull(String param) {
		boolean bool = true;

		if (param == null || "".equals(param.trim())) {
			bool = false;
		} else {
			return bool;
		}
		return bool;
	}

	/**
	 * 判断对象是否为空
	 * 
	 * @param obj
	 *            传入的对象
	 * @return true：不空，false：空
	 */
	public static boolean checkNotNull(Object obj) {
		boolean bool = true;

		if (obj == null) {
			bool = false;
		} else {
			return bool;
		}
		return bool;
	}

	/**
	 * <PRE>
	 * 通过Connection判断数据库类型
	 * 0  连接为空或异常或无法判断
	 * 1 MYSQL
	 * 2 ORACLE
	 * 3 SYBASE
	 * 4 MSSQL
	 * 5 POSTGRESQL
	 * 6 ACCESS
	 * 7 DB2
	 * </PRE>
	 * @param conn 连接
	 * @return 数据库类型编号
	 */
	public static DBType judgeDBType(Connection conn) {
		if (conn == null) {
			return DBType.UNKNOW;
		}
		String driver = null;
		DBType type = DBType.UNKNOW;
		try {
			driver = conn.getMetaData().getDatabaseProductName();
			
			if (driver.toUpperCase().contains("MYSQL")) {
				type = DBType.MYSQL;
			} else if (driver.toUpperCase().contains("ORACLE")) {
				type = DBType.ORACLE;
			} else if (driver.toUpperCase().contains("ADAPTIVE SERVER ENTERPRISE")) {
				type = DBType.SYBASE;
			} else if (driver.toUpperCase().contains("SQLSERVER")) { //MSSQL
				type = DBType.MSSQL;
			} else if (driver.toUpperCase().contains("POSTGRESQL")) {
				type = DBType.POSTGRESQL;
			} else if (driver.toUpperCase().contains("RMIJDBC") 
					|| driver.toUpperCase().contains("OBJECTWEB")) { //ACCESS
				type = DBType.ACCESS;
			} else if (driver.toUpperCase().contains("DB2")) {
				type = DBType.DB2;
			} else {
				type = DBType.UNKNOW;
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
			return DBType.UNKNOW;
		}
		return type;
	}
	
	/**
	 * 检查字符串是否为java关键字
	 * 
	 * @param str 待检查字符串
	 * @return true:是 ; false:不是
	 */
	private static boolean isJavaKeyWord(String str) {
		boolean isKeyWord = false;
		if(str != null && !"".equals(str.trim())) {
			isKeyWord = DBTools.JAVA_KEY_WORD_LIST.contains(str.trim());
		}
		return isKeyWord;
	}
	
	/**
	 * 把字符串列表转换为数组
	 * @param strList 字符串列表
	 * @return 若入参为null则返回null
	 */
	private static String[] strList2Array(List<String> strList) {
		String[] strArray = null;
		if(strList != null) {
			Object[] obj = strList.toArray();
			strArray = Arrays.copyOf(obj, obj.length, String[].class);
		}
		return strArray;
	}
	
	/**
	 * 把字符串数组转换为列表
	 * @param strArray 字符串数组
	 * @return 若入参为null则返回null
	 */
	private static List<String> strArray2List(String[] strArray) {
		return Arrays.asList(strArray);
	}
}
